/*
 * 人人信用管理有限公司版权所有.
 * 
 * @Description:
 * 
 * @author: liyuliang
 * 
 * @date: 20 Apr 2017 10:44:16 am
 * 
 * 注意：本内容仅限于人人信用管理有限公司内部传阅，禁止外泄以及用于其他的商业目的.
 */

package com.rrx360.common.context;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

public class ActionContext {

  private static ThreadLocal<ActionContext> instance = new ThreadLocal<ActionContext>();

  private Map<Object, Object> map;

  public static ActionContext getCurrent() {
    return getCurrent(true);
  }

  public static ActionContext getCurrent(boolean create) {
    ActionContext context = instance.get();
    if (context == null && create) {
      context = new ActionContext();
      instance.set(context);
    }
    return context;
  }

  public static void put(Object key, Object value) {
    getCurrent().putEntry(key, value);
  }

  public static <T> T get(Object key) {
    ActionContext context = instance.get();
    if (context == null) {
      return null;
    }
    return context.getValue(key);
  }

  public static <T> T remove(Object key) {
    ActionContext context = instance.get();
    if (context == null) {
      return null;
    }
    return context.removeEntry(key);
  }

  public static void clear() {
    ActionContext context = instance.get();
    if (context != null && context.map != null) {
      context.map.clear();
    }
  }

  public void putEntry(Object key, Object value) {
    if (map == null) {
      map = new HashMap<>();
    }
    map.put(key, value);
  }

  public <T> T getValue(Object key) {
    if (map == null) {
      return null;
    }
    return (T) map.get(key);
  }

  public <T> T removeEntry(Object key) {
    if (map == null) {
      return null;
    }
    return (T) map.remove(key);
  }

  public Map<Object, Object> getMap() {
    return map;
  }

  public void setMap(Map<Object, Object> map) {
    this.map = map;
  }

  public <T> T run(Callable<T> callable) {
    ActionContext context = ActionContext.getCurrent(false);
    try {
      return callable.call();
    } catch (Exception e) {
      throw new RuntimeException(e);
    } finally {
      if (context == null) {
        ActionContext.clear();
      }
    }
  }

}
